import java.io.*;
import java.text.*;
import java.util.*;

/**
 * This class implements a simple UI we used for testing our system as a whole
 */
public class SystemTest {

    public static String[] productList = {"Ariel", "Pampers", "Febreeze", "Wella", "Clairol", "Head & Shoulders", "Pantene", "Olay", "Crest", "Vicks", "Gillette Mach 3", "Gillette Fusion", "Duracell AA Batteries", "Hugo Boss", "Ghost", "Lacoste", "Max Factor"};

    /**
     * This starts a console program we use to test the system.
     *
     * @param args The command-line arguments - ignored
     */
    public static void main(String[] args) {
        //initialisation order
        LineItem[] initItems = new LineItem[17];
        Order initialiser = new Order(0,-1, initItems, new Date());
        OrdersManager.getOrders().add(initialiser);
        // pre-populate the orders list with data provided by P&G
        List<Order> parsed = DataParser.parseOrders();
        for (Order ord : parsed) {
            OrdersManager.getOrders().add(ord);
        }

        // prompt user for id
        int userId = start();

        // enter the main menu
        while (true) {

            Boolean quit = false;

            // present options
            System.out.println("Please choose an option to proceed:");
            System.out.println("1: Place Single Order");
            System.out.println("2: Place Mass Order");
            System.out.println("3: View Orders");
            System.out.println("4: Confirm Delivery For Pending Order");
            System.out.println("5: Update Orders");
            System.out.println("6: Cancel Orders");
            System.out.println("7: Flee");
            System.out.println("#Press 8 for Dev mode#");

            // pormpt user for selection
            int choice = input();
            switch (choice) {
                case 1:
                    GUIPlaceSingle(userId);
                    break;
                case 2:
                    System.out.println("#Option not included in prototype. \n More budget required#");
                    break;
                case 3:
                    System.out.println("#Option not included in prototype. \n More budget required#");
                    break;
                case 4:
                    confirming(userId);
                    break;
                case 5:
                    System.out.println("#Option not included in prototype. \n More budget required#");
                    break;
                case 6:
                    cancelling(userId);
                    break;
                case 7:
                    quit = true;
                    break;
                case 8:
                    System.out.println("#Dev orders test#");
                    for (Order ord : OrdersManager.getOrders()) {
                        System.out.println("User " + ord.getUserId() + " submitted order " + ord.getOrderId() + " for " + ord.getRequestedDeliveryDate() + " status: " + ord.getStatus());
                    }
                    break;
                default:
                    System.out.println("That's not an option.");
            }

            if (quit) {
                System.out.println("We know where you live. Good Day.");
                System.exit(0);
            }

        }

    }

    /**
     * Prompts the user to input their id into the console
     *
     * @return The user id
     */
    private static int start() {

        int userId = -1;

        System.out.println("   Welcome to SKYNET");
        System.out.println("------------------------");
        System.out.println("Warning - Prototype only \n");

        while (userId < 0) {
            System.out.println("Please enter your user id");
            userId = input();
        }

        return userId;

    }

    /**
     * @return Returns an integer entered into the console
     */
    private static int input() {

        BufferedReader typedchoice = new BufferedReader(new InputStreamReader(System.in));

        int value = -1;

        try {
            value = Integer.valueOf(typedchoice.readLine());
        } catch (Exception e) {
            System.out.println("That's not an option.");
        }

        return value;

    }


        /**
     * This sub-menu deals with placing a single order
     *
     * @param userId The id of the user
     */
    private static void GUIPlaceSingle(int userId) {

        boolean iHateJava = true;

        // initialise the line items array
        LineItem[] newItems = new LineItem[productList.length];
        for (int i = 0; i < newItems.length; i++) {
            newItems[i] = new LineItem(i + 1, 0, new Date());
        }

        while (iHateJava) {

            // present options
            System.out.println("Please select an option");
            System.out.println("1: Browse and select products");
            System.out.println("2: View order");
            System.out.println("3: Place order");
            System.out.println("0: Back");

            // prompt user for selection
            int placeChoice = input();
            switch (placeChoice) {
                case 1:
                    GUIBrowsingSingle(newItems);
                    break;
                case 2:
                    for (int i = 0; i < productList.length; i++) {
                        if (newItems[i].getQuantity() > 0) {
                            System.out.println(newItems[i].getQuantity() + " x " + productList[i]);
                        }
                    }
                    break;
                case 3:
                    iHateJava = GUISubmittingSingle(userId, newItems);
                    break;
                case 0:
                    iHateJava = false;
                    break;
                default:
                    System.out.println("That's not an option.");
            }

        }

    }

    /**
     * This sub-menu deals with adding products to a single order
     *
     * @param newItems An initialised line items array
     */
    private static void GUIBrowsingSingle(LineItem[] newItems) {

        // present options
        System.out.println("\n Products available : \n");
        System.out.println("1:  Ariel                        Number of items per pallette: 45");
        System.out.println("2:  Pampers                      Number of items per pallette: 45");
        System.out.println("3:  Febreeze                     Number of items per pallette: 150");
        System.out.println("4:  Wella                        Number of items per pallette: 250");
        System.out.println("5:  Clairol                      Number of items per pallette: 250");
        System.out.println("6:  Head & Shoulders             Number of items per pallette: 125");
        System.out.println("7:  Pantene                      Number of items per pallette: 225");
        System.out.println("8:  Olay                         Number of items per pallette: 400");
        System.out.println("9:  Crest                        Number of items per pallette: 400");
        System.out.println("10: Vicks                        Number of items per pallette: 400");
        System.out.println("11: Gillette Mach 3              Number of items per pallette: 125");
        System.out.println("12: Gillette Fusion              Number of items per pallette: 125");
        System.out.println("13: Duracell AA Batteries        Number of items per pallette: 300");
        System.out.println("14: Hugo Boss                    Number of items per pallette: 225");
        System.out.println("15: Ghost                        Number of items per pallette: 225");
        System.out.println("16: Lacoste                      Number of items per pallette: 225");
        System.out.println("17: Max Factor                   Number of items per pallette: 300");

        while (true) {

            // prompt user for selection
            System.out.println("Please choose a product, or type 0 to exit.");
            int product = input();

            if (product == 0) {
                break;
            } else if (product < 0 || product > productList.length) {
                System.out.println("Try that again");
            } else {

                int quantity = -1;

                while (true) {

                    System.out.println("Please enter a quantity");
                    quantity = input();

                    if (quantity >= 0) {
                       newItems[product - 1].setQuantity(quantity);
                       break;
                    } else {
                        System.out.println("invalid quantity");
                    }

                }

            }

        }

    }

    /**
     * This sub-menu deals with submitting a single order
     *
     * @param userId The id of the user
     * @param newItems The line items array
     * @return Returns false if order was submitted successfully
     */
    private static boolean GUISubmittingSingle(int userId, LineItem[] newItems) {

        // make sure items were selected before allowing an order to be
        boolean itemOrdered = false;
        for (LineItem item : newItems) {
            if (item.getQuantity() > 0) {
                itemOrdered = true;
            }
        }
        if (!itemOrdered) {
            System.out.println("Please select products first before placing your order.");
            return true;
        }

        boolean dateNotInRange = true;
        Date reqDelivery = null;

        while (dateNotInRange) {

            System.out.println("Please enter when you want the order (DDMMYY HH:mm format)");
            System.out.println("Desired delivery date must be between 24 hours and a week from now");

            DateFormat df = new SimpleDateFormat("ddMMyy HH:mm");
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

            // try and get the date from the input, if it can't be parsed make sure the if below fails
            try {
                reqDelivery = df.parse(reader.readLine());
            } catch(Exception ex) {
                reqDelivery = new Date();
            }

            // get tomorrows date and next weeks
            Calendar cal = Calendar.getInstance();
            cal.setTime(new Date());
            cal.add(Calendar.DATE, 1);
            Date aDayFromNow = cal.getTime();
            cal.add(Calendar.DATE, 6);
            Date aWeekFromNow = cal.getTime();

            // make sure it's in range
            if (reqDelivery.after(aDayFromNow) && reqDelivery.before(aWeekFromNow)) {
                dateNotInRange = false;
            } else {
                System.out.println("Try again.");
            }

        }

        // summarize the users order
        System.out.println("Your order is as follows:\n");
        System.out.println("User ID:" + userId);
        for (int i = 0; i < newItems.length; i++) {
            if (newItems[i].getQuantity() > 0) {
                System.out.println(newItems[i].getQuantity() + " x " + productList[i]);
            }
        }
        System.out.println(reqDelivery.toString());

        // present options
        System.out.println("\n Please select an option:");
        System.out.println("1: Place Order");
        System.out.println("2: Change Order");

        // prompt for selection
        int option = input();
        switch (option) {
            case 1:
                System.out.println("Your order has been placed. We will contact you shortly with possible delivery options.");
                OrdersManager.placeSingleOrder(userId, newItems, reqDelivery);
                return false;
            case 2:
                break;
        }

        return true;

    }

        /**
     * This sub-menu deals with confirming an order if a user is happy with
     * their delivery schedule
     *
     * @param userId The id of the user
     */
    private static void confirming(int userId) {

        Boolean incomplete = true;
        while (incomplete) {

            // prompt user for order id
            System.out.println("Please enter the Order ID of the order you wish to confirm or 0 to go back");

            // check order id is within range
            int orderId = input();
            if (orderId == 0){

                break;
            }
            if ((orderId >= OrdersManager.getOrders().size()) || (orderId < 0)) {
                System.out.println("That's not a valid order.");
            } else {

                // check that order can be confirmed
                if (OrdersManager.getOrders().get(orderId).getStatus() == Order.ESTIMATE_RECEIVED) {

                    // check that order belongs to this user
                    if (OrdersManager.getOrders().get(orderId).getUserId() == userId) {

                        // check if any item is going to be delivered later than requested
                        Date deliv = OrdersManager.getOrders().get(orderId).getRequestedDeliveryDate();
                        boolean fullDeliveryWhenRequested = true;
                        for (LineItem item : OrdersManager.getOrders().get(orderId).getItems()) {
                            if (item.getDeliveryDate().after(deliv)) {
                                fullDeliveryWhenRequested = false;
                            }
                        }

                        // if everything will be on time
                        if (fullDeliveryWhenRequested) {

                            Boolean consideringOrder = true;
                            while (consideringOrder) {

                                // present options
                                System.out.println("Estimated Delivery Date: " + deliv.toString());
                                System.out.println("\n Please press 1 to confirm the order, 2 to cancel the order or 0 to back");

                                // prompt user for selection
                                int confirm = input();
                                if (confirm == 1) {
                                    OrdersManager.confirmOrder(orderId);
                                    consideringOrder = false;
                                } else if (confirm == 2) {
                                    OrdersManager.cancelOrder(orderId);
                                    consideringOrder = false;
                                } else if (confirm == 0) {
                                    consideringOrder = false;
                                }

                            }

                        } else {
                            // WE HAVE NOT IMPLEMENTED THE POSSIBLE CHOICES IF AN ORDER WOULD BE DELIVERED LATER THAN REQUESTED.
                            // IN ORDER TO IMPLEMENT IT WE WOULD OFFER THE CHOICE OF SPLITTING THE ORDER, GETTING EVERYTHING AT A LATER DATE OR ONLY SHIPPING A SUBSET OF ITEMS.
                            // OF THESE, SPLITTING AN ORDER WOULD CREATE ADDITIONAL ORDERS, SHIPPING A SUBSET WOULD DISPLAY WHEN ITEMS COULD BE DELIVERED AND SET THE QUANTITY OF UNWANTED ITEMS TO ZERO.
                        }

                    } else {
                        System.out.println("That's not your order.");
                    }

                } else {
                    System.out.println("That order can not be confirmed.");
                }

            }

        }

    }

    /**
     * This sub-menu deals with canceling an order
     *
     * @param userId The id of the user
     */
    private static void cancelling(int userId) {

        Boolean cancelling = true;
        while (cancelling) {

            // prompt user for a valid order id
            System.out.println("Please enter the Order ID of the order you wish to cancel or -1 to go back");
            int orderId = input();
            if ((orderId >= OrdersManager.getOrders().size()) || (orderId < 0)) {
                System.out.println("That's not a valid order.");
            } else if (orderId == -1) {
                System.out.println("Going back to main menu.");
            } else {

                if (OrdersManager.getOrders().get(orderId).getUserId() == userId) {

                    Boolean consideringOrder = true;
                    while (consideringOrder) {

                        // summarize the users order
                        System.out.println("Your order is as follows:\n");
                        System.out.println("User ID:" + userId);
                        for (int i = 0; i < OrdersManager.getOrderFromId(orderId).getItems().length; i++) {
                            if (OrdersManager.getOrderFromId(orderId).getItems()[i].getQuantity() > 0) {
                                System.out.println(OrdersManager.getOrderFromId(orderId).getItems()[i].getQuantity() + " x " + productList[i]);
                            }
                        }
                        System.out.println(OrdersManager.getOrderFromId(orderId).getRequestedDeliveryDate().toString());

                        // prompt user for confirmation
                        System.out.println("\n Please press 1 to cancel the order or 0 to back");
                        int confirm = input();
                        if (confirm == 1) {
                            OrdersManager.cancelOrder(orderId);
                            consideringOrder = false;
                        } else if (confirm == 0) {
                            consideringOrder = false;
                        }

                    }

                } else {
                    System.out.println("That's not your order.");
                }

            }

        }

    }

}
